package com.wan37.gate.server;

import com.wan37.gate.global.dispatcher.ClientMessageDispatcher;
import com.wan37.gate.handler.GateServerHandler;
import com.wan37.gate.handler.GateServerHeartbeatHandler;
import com.wan37.protobuf.ParseRegistryMap;
import com.wan37.protobuf.codec.ProtoPacketDecoder;
import com.wan37.protobuf.codec.ProtoPacketEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;

/**
 * Gate网关服务器
 *
 * @author : luoyong
 * @date : 2020-05-26 17:40
 **/
public class GateServer implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(GateServer.class);

    /**
     * gateServer监听的端口
     */
    private int port;

    /**
     * 处理客户端发送过来消息的分发器(spring注入)
     */
    private ClientMessageDispatcher clientMessageDispatcher;


    @Override
    public void run() {
        this.startGateServer();
    }

    /**
     * 启动消息分发器
     */
    private void startDispatcher() {
        new Thread(clientMessageDispatcher).start();
    }

    private void startGateServer() {
        //1)配置连接
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();

//                        pipeline.addLast("IdleStateHandler", new IdleStateHandler(20,20,20));

                        pipeline.addLast("LengthFieldBasedFrameDecoder",
                                new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 4, 0));

                        pipeline.addLast("ProtobufPacketDecoder", new ProtoPacketDecoder());

                        pipeline.addLast("GateServerHeartbeatHandler", new GateServerHeartbeatHandler("gateServer"));

                        pipeline.addLast("GateServerHandler", new GateServerHandler());

                        pipeline.addLast("protobufPacketEncoder", new ProtoPacketEncoder());

                    }
                });

        ChannelFuture future = serverBootstrap.bind(new InetSocketAddress(this.port));
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (future.isSuccess()) {
                    ParseRegistryMap.initRegistry();
                    startDispatcher();
                    logger.info("[GateServer] 成功启动, 初始化工作完成, 正在等待客户端的连接...");
                } else {
                    logger.error("[GateServer] 启动失败, 请重试!");
                }
            }
        });
    }


    public void setPort(int port) {
        this.port = port;
    }

    public void setClientMessageDispatcher(ClientMessageDispatcher clientMessageDispatcher) {
        this.clientMessageDispatcher = clientMessageDispatcher;
    }
}
